package com.wechat.gateway.ratelimit;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.time.Instant;

/**
 * 令牌桶实体 - 支持JSON序列化
 * 与Lua脚本中的JSON结构保持一致
 */
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonIgnoreProperties(ignoreUnknown = true)
public class TokenBucket {

    /**
     * 桶容量（最大令牌数）
     */
    @JsonProperty("capacity")
    private long capacity;

    /**
     * 当前令牌数
     */
    @JsonProperty("tokens")
    private long tokens;

    /**
     * 令牌生成速率（每秒生成的令牌数）
     */
    @JsonProperty("refillRate")
    private double refillRate;

    /**
     * 上次更新时间戳（秒）
     */
    @JsonProperty("lastRefillTime")
    private long lastRefillTime;

    /**
     * 数据更新时间戳（秒）
     */
    @JsonProperty("updatedAt")
    private Long updatedAt;

    /**
     * 桶创建时间戳（秒）
     */
    @JsonProperty("createdAt")
    private Long createdAt;

    /**
     * 桶重置时间戳（秒）
     */
    @JsonProperty("resetAt")
    private Long resetAt;

    /**
     * 当前查询时间戳（秒）- 用于状态查询
     */
    @JsonProperty("currentTime")
    private Long currentTime;

    /**
     * 计算令牌利用率
     */
    public double getUtilizationRate() {
        if (capacity == 0) {
            return 0.0;
        }
        return (double) (capacity - tokens) / capacity;
    }

    /**
     * 检查是否有足够的令牌
     */
    public boolean hasEnoughTokens(long requiredTokens) {
        return tokens >= requiredTokens;
    }

    /**
     * 计算到满桶的时间（秒）
     */
    public long getTimeToFull() {
        if (tokens >= capacity || refillRate <= 0) {
            return 0;
        }
        return (long) Math.ceil((capacity - tokens) / refillRate);
    }

    /**
     * 获取桶的状态描述
     */
    public String getStatusDescription() {
        double utilizationRate = getUtilizationRate() * 100;
        return String.format("容量:%d, 可用:%d, 利用率:%.1f%%, 补充速率:%.2f/s",
                capacity, tokens, utilizationRate, refillRate);
    }

    /**
     * 创建一个新的令牌桶
     */
    public static TokenBucket create(long capacity, double refillRate) {
        long now = Instant.now().getEpochSecond();
        return TokenBucket.builder()
                .capacity(capacity)
                .tokens(capacity)
                .refillRate(refillRate)
                .lastRefillTime(now)
                .createdAt(now)
                .updatedAt(now)
                .build();
    }

    /**
     * 创建一个空的令牌桶
     */
    public static TokenBucket empty(long capacity, double refillRate) {
        long now = Instant.now().getEpochSecond();
        return TokenBucket.builder()
                .capacity(capacity)
                .tokens(0)
                .refillRate(refillRate)
                .lastRefillTime(now)
                .createdAt(now)
                .updatedAt(now)
                .build();
    }
}